package cmap

import (
	"reflect"
	"bytes"
	"fmt"
)

type OrderedMap interface {
	GenericMap
	// 获取第一个键值。若无任何键值对则返回nil。
	FirstKey() interface{}
	// 获取最后一个键值。若无任何键值对则返回nil。
	LastKey() interface{}
	// 获取由小于键值toKey的键值所对应的键值对组成的OrderedMap类型值。
	HeadMap(toKey interface{}) OrderedMap
	// 获取由小于键值toKey且大于等于键值fromKey的键值所对应的键值对组成的OrderedMap类型值。
	SubMap(fromKey interface{}, toKey interface{}) OrderedMap
	// 获取由大于等于键值fromKey的键值所对应的键值对组成的OrderedMap类型值。
	TailMap(fromKey interface{}) OrderedMap
}

type myOrderedMap struct {
	keys Keys
	elemType reflect.Type
	m map[interface{}] interface{}
}

// 获取给定键值对应的元素值。若没有对应元素值则返回nil。
func (omap *myOrderedMap) Get(key interface{}) interface{} {
	return omap.m[key]
}
// 添加键值对，并返回与给定键值对应的旧的元素值。若没有旧元素值则返回(nil, true)。
func (omap *myOrderedMap) Put(key interface{}, elem interface{}) (interface{}, bool) {
	if !omap.isAcceptableElem(elem) {
		return nil, false
	}
	oldElem, ok := omap.m[key]
	omap.m[key] = elem
	if !ok {
		omap.keys.Add(key)
	}
	return oldElem, true
}
// 删除与给定键值对应的键值对，并返回旧的元素值。若没有旧元素值则返回nil。
func (omap *myOrderedMap) Remove(key interface{}) interface{} {
	oldV, ok := omap.m[key]
	delete(omap.m, key)
	if ok {
		omap.keys.Remove(key)
	}
	return oldV
}
// 清除所有的键值对。
func (omap *myOrderedMap) Clear() {
	omap.m = make(map[interface{}]interface{})
	omap.keys.Clear()
}
// 获取键值对的数量。
func (omap *myOrderedMap) Len() int {
	return len(omap.m)
}
// 判断是否包含给定的键值。
func (omap *myOrderedMap) Contains(key interface{}) bool {
	_, ok := omap.m[key]
	return ok
}
// 获取已排序的键值所组成的切片值。
func (omap *myOrderedMap) Keys() []interface{} {
	initLen := omap.keys.Len()
	result := make([]interface{}, initLen)
	actualLen := 0
	for _, key := range omap.keys.GetAll() {
		if actualLen < initLen {
			result[actualLen] = key
		}else{
			result = append(result, key)
		}
		actualLen++
	}
	return result
}
// 获取已排序的元素值所组成的切片值。
func (omap *myOrderedMap) Elems() []interface{} {
	initLen := omap.keys.Len()
	result := make([]interface{}, initLen)
	actualLen := 0
	for _, key := range omap.keys.GetAll() {
		elem := omap.m[key]
		if actualLen < initLen {
			result[actualLen] = elem
		}else{
			result = append(result, elem)
		}
		actualLen++
	}
	return result
}
// 获取已包含的键值对所组成的字典值。
func (omap *myOrderedMap) ToMap() map[interface{}]interface{} {
	replica := make(map[interface{}]interface{})
	for k, v := range omap.m {
		replica[k] = v
	}
	return replica
}
// 获取键的类型。
func (omap *myOrderedMap) KeyType() reflect.Type {
	return omap.keys.ElemType()
}
// 获取元素的类型。
func (omap *myOrderedMap) ElemType() reflect.Type {
	return omap.elemType
}
// 获取第一个键值。若无任何键值对则返回nil。
func (omap *myOrderedMap) FirstKey() interface{} {
	if omap.Len() == 0 {
		return nil
	}
	return omap.keys.Get(0)
}
// 获取最后一个键值。若无任何键值对则返回nil。
func (omap *myOrderedMap) LastKey() interface{} {
	length := omap.Len()
	if length == 0 {
		return nil
	}
	return omap.keys.Get(length - 1)
}
// 获取由小于键值toKey的键值所对应的键值对组成的OrderedMap类型值。
func (omap *myOrderedMap) HeadMap(toKey interface{}) OrderedMap {
	return omap.SubMap(nil, toKey)
}
// 获取由小于键值toKey且大于等于键值fromKey的键值所对应的键值对组成的OrderedMap类型值。
func (omap *myOrderedMap) SubMap(fromKey interface{}, toKey interface{}) OrderedMap {
	newOMap := &myOrderedMap{
		keys: NewKeys(omap.keys.CompareFunc(), omap.keys.ElemType()),
		elemType: omap.elemType,
		m: make(map[interface{}]interface{}),
	}
	oldLen := omap.Len()
	if oldLen == 0 {
		return newOMap
	}
	beginIndex, ok := omap.keys.Search(fromKey)
	if !ok{
		beginIndex = 0
	}
	endIndex, ok := omap.keys.Search(toKey)
	if !ok{
		endIndex = oldLen
	}
	for i := beginIndex; i < endIndex; i++ {
		key := omap.keys.Get(i)
		newOMap.Put(key, omap.m[key])
	}
	return newOMap
}
// 获取由大于等于键值fromKey的键值所对应的键值对组成的OrderedMap类型值。
func (omap *myOrderedMap) TailMap(fromKey interface{}) OrderedMap {
	return omap.SubMap(fromKey, nil)
}

func (omap *myOrderedMap) String() string {
	var buf bytes.Buffer
	buf.WriteString("OrderedMap<")
	buf.WriteString(omap.keys.ElemType().Kind().String())
	buf.WriteString(",")
	buf.WriteString(omap.elemType.Kind().String())
	buf.WriteString(">{")
	first := true
	omapLen := omap.Len()
	for i := 0; i < omapLen; i++ {
		if first {
			first = false
		} else {
			buf.WriteString(" ")
		}
		key := omap.keys.Get(i)
		buf.WriteString(fmt.Sprintf("%v", key))
		buf.WriteString(":")
		buf.WriteString(fmt.Sprintf("%v", omap.m[key]))
	}
	buf.WriteString("}")
	return buf.String()
}


func (omap *myOrderedMap) isAcceptableElem(v interface{}) bool{
	if v == nil {
		return false
	}
	if reflect.TypeOf(v) != omap.elemType {
		return false
	}
	return true
}

func NewOrderedMap(keys Keys, elemType reflect.Type) OrderedMap {
	return &myOrderedMap{
		keys:keys,
		elemType:elemType,
		m:make(map[interface{}]interface{}),
	}
}